// Rover Metallic - stable panel reflection for Component 3.008_armup.
// Also used by Component 3.008_armup_gliding_pose. No procedural micro-glint cells.
#include "RoverMetallic_C3008_armup_PanelParameters.hlsl"

cbuffer cb4 : register(b4) { float4 cb4[177]; }
cbuffer cb3 : register(b3) { float4 cb3[43]; }
cbuffer cb2 : register(b2) { float4 cb2[43]; }
cbuffer cb1 : register(b1) { float4 cb1[4]; }
cbuffer cb0 : register(b0) { float4 cb0[283]; }

float3 RoverWingWorldPosition(float4 screenPosition)
{
    float4 projected = cb0[45] * screenPosition.y;
    projected += cb0[44] * screenPosition.x;
    projected += cb0[46] * screenPosition.z;
    projected += cb0[47];
    return projected.xyz / max(abs(projected.w), 0.0001);
}

float RoverWingPanelMask(float2 uv)
{
    // Continuous low-frequency bands, not discrete cells. Two warped sine fields
    // create large irregular zones without pixel-sized sparkle.
    float2 p = uv * RM_WING_PANEL_SCALE;
    float warp = sin((p.y * 2.1 + p.x * 0.35) * 6.2831853) * RM_WING_PANEL_WARP;
    float a = sin((p.x * 0.82 + p.y * 0.19 + warp * 0.08) * 6.2831853);
    float b = sin((p.y * 0.63 - p.x * 0.14 + warp * 0.05 + 0.37) * 6.2831853);
    float pattern = saturate(0.5 + 0.5 * (a * 0.68 + b * 0.32));
    return lerp(1.0 - RM_WING_PANEL_VARIATION, 1.0, pattern);
}

float3 RoverWingBuildTangent(float3 N, float4 tangentInput, out float3 B)
{
    float3 T = tangentInput.xyz - N * dot(tangentInput.xyz, N);
    float lenT = length(T);
    if (lenT < 0.0001)
    {
        float3 fallback = abs(N.z) < 0.95 ? float3(0.0, 0.0, 1.0) : float3(0.0, 1.0, 0.0);
        T = normalize(cross(fallback, N));
    }
    else T /= lenT;

    float handedness = tangentInput.w < 0.0 ? -1.0 : 1.0;
    B = normalize(cross(N, T)) * handedness;
    return T;
}

float RoverWingAnisotropicLobe(float3 N, float3 T, float3 B, float3 V, float3 L)
{
    float3 H = normalize(V + L);
    float ndh = saturate(dot(N, H));
    float th = dot(T, H);
    float bh = dot(B, H);

    // Stable elliptical lobe. Low ALONG_SHARPNESS makes it long in one direction,
    // while CROSS_SHARPNESS keeps the band defined across its width.
    float ellipse = exp(-(th * th * RM_WING_CROSS_SHARPNESS + bh * bh * RM_WING_ALONG_SHARPNESS));
    float broad = pow(ndh, RM_WING_NORMAL_POWER) * ellipse;
    float core = pow(ndh, RM_WING_CORE_POWER) * ellipse;
    return broad + core * RM_WING_WHITE_CORE;
}

void main(
    linear centroid float4 v0 : TEXCOORD10,
    linear centroid float4 v1 : TEXCOORD11,
    float2 v2 : TEXCOORD0,
    float2 v3 : TEXCOORD1,
    float2 v4 : TEXCOORD2,
    float2 v5 : TEXCOORD3,
    float2 v6 : TEXCOORD4,
    float4 v7 : VELOCITY_PREV_POS0,
    float4 v8 : SV_Position0,
    uint v9 : SV_IsFrontFace0,
    out float4 o0 : SV_Target0,
    out float4 o3 : SV_Target3)
{
    float3 worldPosition = RoverWingWorldPosition(v8);
    float3 V = normalize(-worldPosition);
    float3 N = normalize(v1.xyz);
    if (v9 == 0) N = -N;

    float3 B;
    float3 T = RoverWingBuildTangent(N, v0, B);

    float3 L1 = normalize(RM_WING_LIGHT_A);
    float3 L2 = normalize(RM_WING_LIGHT_B);

    float lobe1 = RoverWingAnisotropicLobe(N, T, B, V, L1) * RM_WING_PRIMARY_STRENGTH;
    float lobe2 = RoverWingAnisotropicLobe(N, T, B, V, L2) * RM_WING_SECONDARY_STRENGTH;
    float panelMask = RoverWingPanelMask(v2);

    float ndv = saturate(abs(dot(N, V)));
    float fresnel = pow(saturate(1.0 - ndv), RM_WING_FRESNEL_POWER) * RM_WING_FRESNEL_STRENGTH;

    float reflection = (lobe1 + lobe2) * panelMask + fresnel;
    float3 finalHighlight = RM_WING_METAL_COLOR * reflection;

    o0 = float4(max(finalHighlight, 0.0), 0.0);
    o3 = float4(0.0, 0.0, 0.0, 0.0);
}
